package com.le.tester.onjava8.l1_10_2;

import java.util.EnumMap;

/**
 * createTime：2022/10/27 10:57
 * description：枚举实现自动售卖机
 */

enum Category {

    MONEY(Input.NICKEL, Input.DIME),
    ITEM_SELECTION(Input.DIME, Input.NICKEL),
    QUIT_TRANSACTION(Input.ABORT_TRANSACTION),
    SHUT_DOWN(Input.STOP);

    private Input[] values;

    Category(Input... types) {
        values = types;
    }

    private static EnumMap<Input, Category> categories = new EnumMap<>(Input.class);

    static {
        for (Category c : Category.class.getEnumConstants())
            for (Input type : c.values)
                categories.put(type, c);
    }

    public static Category categorize(Input input) {
        return categories.get(input);
    }
}

public class VendingMachine {

    private static State state = State.RESTING;
    private static int amount = 0;
    private static Input selection = null;

    enum StateDuration {TRANSIENT}

    enum State {
        RESTING {
            void next(Input input) {
                switch (Category.categorize(input)) {
                    case MONEY:
                        amount += input.amount();
                        state = ADDING_MONEY;
                        break;
                    case SHUT_DOWN:
                        state = TERMINAL;
                    default:
                }
            }
        },

        ADDING_MONEY {
            void next(Input input) {
                switch (Category.categorize(input)) {
                    case MONEY:
                        amount += input.amount();
                        break;
                    case ITEM_SELECTION:
                        selection = input;
                        if (amount < selection.amount())
                            System.out.println("Insufficient money for" + selection);
                        else state = DISPENSING;
                        break;
                    case QUIT_TRANSACTION:
                        state = TERMINAL;
                    default:
                }
            }
        },
        TERMINAL {
            void output() {
                System.out.println("Halted");
            }
        },
        GIVING_CHANGE(StateDuration.TRANSIENT) {
            void next() {
                if (amount < 0) {
                    System.out.println("Your change:" + amount);
                    amount = 0;
                }
                state = RESTING;
            }
        },

        DISPENSING(StateDuration.TRANSIENT) {
            void next() {
                System.out.println("here is your " + selection);
                amount -= selection.amount();
                state = GIVING_CHANGE;
            }
        };

        private boolean isTransient = false;

        State() {
        }

        State(StateDuration stateDuration) {
            isTransient = true;
        }

        void next() {
            throw new RuntimeException();
        }

        void output() {
            throw new RuntimeException();
        }
    }


}
